package com.daffodil.util;

import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

import org.apache.commons.collections4.MapUtils;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * @author yweijian
 * @date 2021年8月4日
 * @version 1.0
 * @description
 */
@Slf4j
public class JacksonUtils {

	private static ObjectMapper mapper;

	static {
		mapper = new ObjectMapper();
		// 如果存在未知属性，则忽略不报错
		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		// 允许key没有双引号
		mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
		// 允许key有单引号
		mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
		// 允许整数以0开头
		mapper.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true);
		// 允许字符串中存在回车换行控制符
		mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
	}

	/**
	 * 将json对象转成字符串格式
	 * @param obj json对象（无美化格式）
	 * @return
	 */
	public static String toJSONString(Object obj) {
		return obj != null ? toJSONString(obj, () -> "", false) : "";
	}

	/**
	 * 将json对象转成字符串格式
	 * @param obj json对象
	 * @param format 是否格式美化
	 * @return
	 */
	public static String toJSONString(Object obj, boolean format) {
		return obj != null ? toJSONString(obj, () -> "", format) : "";
	}

	/**
	 * 将json对象转成字符串格式
	 * @param obj json对象
	 * @param supplier 对外函数
	 * @param format 是否格式美化
	 * @return
	 */
	public static String toJSONString(Object obj, Supplier<String> supplier, boolean format) {
		try {
			if (obj == null) {
				return supplier.get();
			}
			if (obj instanceof String) {
				return obj.toString();
			}
			if (obj instanceof Number) {
				return obj.toString();
			}
			if (format) {
				return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
			}
			return mapper.writeValueAsString(obj);
		} catch (Throwable e) {
			log.error(String.format("toJSONString %s", obj != null ? obj.toString() : "null"), e);
		}
		return supplier.get();
	}

	/**
	 * 转成java对象
	 * @param value
	 * @param clazz
	 * @return
	 */
	public static <T> T toJavaObject(String value, Class<T> clazz) {
		return StringUtils.isNotBlank(value) ? toJavaObject(value, clazz, () -> null) : null;
	}

	/**
	 * 转成java对象
	 * @param obj
	 * @param clazz
	 * @return
	 */
	public static <T> T toJavaObject(Object obj, Class<T> clazz) {
		return obj != null ? toJavaObject(toJSONString(obj), clazz, () -> null) : null;
	}

	/**
	 * 转成java对象
	 * @param value
	 * @param clazz
	 * @param supplier
	 * @return
	 */
	public static <T> T toJavaObject(String value, Class<T> clazz, Supplier<T> supplier) {
		return toJavaObject(value, clazz, mapper, supplier);
	}
	
	/**
	 * 转成java对象
	 * @param obj
	 * @param clazz
	 * @param supplier
	 * @return
	 */
	public static <T> T toJavaObject(Object obj, Class<T> clazz, Supplier<T> supplier) {
		return obj != null ? toJavaObject(toJSONString(obj), clazz, mapper, supplier) : null;
	}
	
	/**
	 * 
	 * @param obj
	 * @param clazz
	 * @param mapper
	 * @param supplier
	 * @return
	 */
	public static <T> T toJavaObject(Object obj, Class<T> clazz, ObjectMapper mapper, Supplier<T> supplier) {
		return obj != null ? toJavaObject(toJSONString(obj), clazz, mapper, supplier) : null;
	}
	
	/**
	 *  转成java对象
	 * @param value
	 * @param clazz
	 * @param mapper
	 * @param supplier
	 * @return
	 */
	public static <T> T toJavaObject(String value, Class<T> clazz, ObjectMapper mapper, Supplier<T> supplier) {
		try {
			if (StringUtils.isBlank(value)) {
				return supplier.get();
			}
			return mapper.readValue(value, clazz);
		} catch (Throwable e) {
			log.error(String.format("toJavaObject exception: %s %s", value, clazz), e);
		}
		return supplier.get();
	}

	/**
	 * 获取值为Long
	 * @param map
	 * @param key
	 * @return
	 */
	public static Long getAsLong(Map<String, Object> map, String key) {
		if (MapUtils.isEmpty(map)) {
			return 0L;
		}
		String value = String.valueOf(map.get(key));
		if (StringUtils.isBlank(value) || !StringUtils.isNumeric(value)) {
			return 0L;
		}
		try {
			return Long.valueOf(value);
		} catch (Throwable e) {
			log.error(String.format("getAsLong exception: %s", key), e);
		}
		return 0L;
	}

	/**
	 * 获取值为Double
	 * @param map
	 * @param key
	 * @return
	 */
	public static Double getAsDouble(Map<String, Object> map, String key) {
		if (MapUtils.isEmpty(map)) {
			return 0.0;
		}
		String value = String.valueOf(map.get(key));
		if (StringUtils.isBlank(value) || !StringUtils.isNumeric(value)) {
			return 0.0;
		}
		try {
			return Double.valueOf(value);
		} catch (Throwable e) {
			log.error(String.format("getAsDouble exception: %s", key), e);
		}
		return 0.0;
	}

	/**
	 * 获取值为Float
	 * @param map
	 * @param key
	 * @return
	 */
	public static Float getAsFloat(Map<String, Object> map, String key) {
		if (MapUtils.isEmpty(map)) {
			return 0f;
		}
		String value = String.valueOf(map.get(key));
		if (StringUtils.isBlank(value) || !StringUtils.isNumeric(value)) {
			return 0f;
		}
		try {
			return Float.valueOf(value);
		} catch (Throwable e) {
			log.error(String.format("getAsFloat exception: %s", key), e);
		}
		return 0f;
	}

	/**
	 * 获取值为Integer
	 * @param map
	 * @param key
	 * @return
	 */
	public static Integer getAsInteger(Map<String, Object> map, String key) {
		if (MapUtils.isEmpty(map)) {
			return 0;
		}
		String value = String.valueOf(map.get(key));
		if (StringUtils.isBlank(value) || !StringUtils.isNumeric(value)) {
			return 0;
		}
		try {
			return Integer.valueOf(value);
		} catch (Throwable e) {
			log.error(String.format("getAsInteger exception: %s", key), e);
		}
		return 0;
	}

	/**
	 * 获取值为String
	 * @param map
	 * @param key
	 * @return
	 */
	public static String getAsString(Map<String, Object> map, String key) {
		if (MapUtils.isEmpty(map)) {
			return null;
		}
		try {
			return String.valueOf(map.get(key));
		} catch (Throwable e) {
			log.error(String.format("getAsString exception: %s", key), e);
		}
		return null;
	}

	/**
	 * 获取值为Map
	 * @param map
	 * @param key
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, Object> getAsMap(Map<String, Object> map, String key) {
		if (MapUtils.isEmpty(map)) {
			return null;
		}
		try {
			return (Map<String, Object>) map.get(key);
		} catch (Throwable e) {
			log.error(String.format("getAsMap exception: %s", key), e);
		}
		return null;
	}

	/**
	 * 获取值为List
	 * @param map
	 * @param key
	 * @return
	 */
	public static List<?> getAsList(Map<String, Object> map, String key) {
		if (MapUtils.isEmpty(map)) {
			return null;
		}
		try {
			return (List<?>) map.get(key);
		} catch (Throwable e) {
			log.error(String.format("getAsList exception: %s", key), e);
		}
		return null;
	}

}
